﻿using System;

using DDDSample.Common.Validate;

namespace DDDSample.Domain.Model.Locations
{
	/// <summary>
	/// A location is our model is stops on a journey, such as cargo
	/// origin or destination, or carrier movement endpoints.
	/// 
	/// It is uniquely identified by a UN Locode.
	/// </summary>
	public sealed class Location : Entity<Location>
	{
		private UnLocode unLocode;
		private string name;

		/// <summary>
		/// Special Location object that marks an unknown location.
		/// </summary>
		public static readonly Location UNKNOWN = new Location(new UnLocode("XXXXX"), "Unknown location");

		/// <summary>
		/// Internal constructor, visible for test only.
		/// </summary>
		/// <param name="unLocode">UN Locode</param>
		/// <param name="name">location name</param>
		/// <exception cref="ArgumentNullException">if the UN Locode or name is null</exception>
		internal Location(UnLocode unLocode, string name)
		{
			Validate.NotNull(unLocode);
			Validate.NotNull(name);

			this.unLocode = unLocode;
			this.name = name;
		}

		/// <summary>
		/// UN Locode for this location.
		/// </summary>
		public UnLocode UnLocode
		{
			get { return this.unLocode; }
		}

		/// <summary>
		/// Actual name of this location, e.g. "Stockholm".
		/// </summary>
		public string Name
		{
			get { return this.name; }
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="obj">object to compare</param>
		/// <returns>Since this is an entiy this will be true iff UN locodes are equal.</returns>
		public override bool Equals(object obj)
		{
			if (obj == null) {
				return false;
			}
			if (this == UNKNOWN || obj == UNKNOWN) {
				return this == obj;
			}
			if (!(obj is Location)) {
				return false;
			}
			Location other = (Location)obj;
			return SameIdentityAs(other);
		}

		public override bool SameIdentityAs(Location other)
		{
			return this.unLocode.SameValueAs(other.unLocode);
		}

		public override int GetHashCode()
		{
			return this.unLocode.GetHashCode();
		}

		private Location()
		{
			// Needed by Hibernate
		}

		// Auto-generated surrogate key
		private long id;
	}
}
